<?php


namespace seecms\lib\builder;

use seecms\lib\builder\alert\Alert;
use seecms\lib\builder\alert\DangerAlert;
use seecms\lib\builder\button\Button;
use seecms\lib\builder\button\DeleteButton;
use seecms\lib\builder\button\EditButton;
use seecms\lib\builder\button\PageButton;
use seecms\lib\builder\button\ReadButton;
use seecms\lib\builder\column\Column;
use seecms\lib\builder\column\ImageColumn;
use seecms\lib\builder\column\SwitchColumn;
use seecms\lib\builder\column\TextColumn;
use seecms\lib\builder\control\Control;
use seecms\lib\builder\control\DatetimeControl;
use seecms\lib\builder\control\FileControl;
use seecms\lib\builder\control\HiddenControl;
use seecms\lib\builder\control\ImageControl;
use seecms\lib\builder\control\InputControl;
use seecms\lib\builder\control\PasswordControl;
use seecms\lib\builder\control\RadioControl;
use seecms\lib\builder\control\SelectControl;
use seecms\lib\builder\query\DateQuery;
use seecms\lib\builder\query\Query;
use seecms\lib\builder\query\TextQuery;
use seecms\lib\builder\toolbar\CreateToolbar;
use seecms\lib\builder\toolbar\DeleteToolbar;
use seecms\lib\builder\toolbar\NormalToolbar;
use seecms\lib\Transfer;
use seecms\See;
use seecms\SeeLang;

class PageParse
{
    protected $dictionary = [];

    public function __construct($dictionary = null)
    {
        if ($dictionary) {
            $this->setDictionary($dictionary);
        }
    }

    public static function global($dictionary = null): PageParse
    {
        return new self(SeeLang::instance()->global($dictionary));
    }

    /**
     * 设置字典
     * @param $dictionary
     * @return $this
     */
    public function setDictionary($dictionary): PageParse
    {
        if (!is_array($dictionary)) {
            $dictionary = [];
        }

        $this->dictionary = $dictionary;

        return $this;
    }

    /**
     * 转化label
     * @param string $name
     * @return mixed|string
     */
    public function transferLabel(string $name)
    {
        $text = $this->dictionary[$name] ?? '';
        if (empty($text) && preg_match('/_text$/', $name)) {
            $name = substr($name, 0, -5);
            $text = $this->dictionary[$name] ?? '';
        }
        return $text;
    }

    /**
     * @param $queries
     * @return Query[]
     */
    public function query($queries): array
    {
        $data = [];

        if (empty($queries)) {
            return $data;
        }

        $enter = SeeLang::instance()->get('enter');
        $select = SeeLang::instance()->get('select');

        foreach ($queries as $field) {
            if (is_string($field)) {
                if ($field === 'created_at') {
                    $query = new DateQuery();
                } else {
                    $query = new TextQuery();
                }
                $query->setName($field);
            } else {
                $query = $field;
            }

            if (!$query instanceof Control) {
                continue;
            }

            $label = $this->transferLabel($query->getName());
            $query->setLabel($label);

            if (empty($query->getPlaceholder())) {
                if ($query->getType() === 'select') {
                    $placeholder = $select . $label;
                } else {
                    $placeholder = $enter . $label;
                }
                $query->setPlaceholder($placeholder);
            }

            $data[] = $query;
        }

        return $data;
    }

    /**
     * @param $columns
     * @return Column[]
     */
    public function columns($columns): array
    {
        $data = [];

        $page = See::config()->page;
        $images = $page->columnImg();
        $switch = $page->columnSwitch();

        foreach ($columns as $item) {
            /**
             * @var Column $column
             */
            if (is_string($item)) {
                $item = explode('.', $item);
                $field = $item[0];
                $width = $item[1] ?? 0;
                if (in_array($field, $images)) {
                    $column = new ImageColumn();
                } elseif (in_array($field, $switch)) {
                    $column = new SwitchColumn();
                } else {
                    $column = new TextColumn();
                    if ($field == 'sort') {
                        $column->setEdit();
                    }
                }

                $title = $this->transferLabel($field);
                $column->setField($field);
                $column->setTitle($title);

                if ($field == 'created_at' && $width == 0) {
                    $width = 180;
                }

                if ($width) {
                    $column->setWidth(intval($width));
                }

            } else {
                $column = $item;
            }

            $field = $column->getField();
            $title = $column->getTitle() ?: $this->transferLabel($field);
            $column->setTitle($title);

            $data[$field] = $column;
        }

        return $data;
    }

    /**
     * @param $columns
     * @return array
     */
    public function columnsTransfer($columns): array
    {
        $columns = $this->columns($columns);

        $data = [];
        foreach ($columns as $column) {
            $data[] = [
                'type' => $column->getType(),
                'field' => $column->getField(),
                'title' => $column->getTitle(),
                'sort' => $column->getSortable(),
                'templet' => $column->getTemplate(),
                'width' => $column->getWidth(),
                'extra' => $column->getExtra(),
                'fixed' => $column->getFixed(),
                'edit' => $column->getEdit(),
            ];
        }

        return $data;
    }

    /**
     * @param $alerts
     * @return Alert[]
     */
    public function alerts($alerts): array
    {
        $data = [];
        if (empty($alerts)) {
            return $data;
        }

        if (is_string($alerts)) {
            $alerts = [$alerts];
        }

        foreach ($alerts as $alert) {
            if (is_string($alert)) {
                $alt = new DangerAlert();
                $alt->setText($alert);
            } else {
                $alt = $alert;
            }

            if ($alt instanceof Alert) {
                $data[] = $alt;
            }
        }

        return $data;
    }

    /**
     * @param $name
     * @return DeleteButton|EditButton|PageButton|ReadButton|null
     */
    public function button($name)
    {
        if (empty($name)) {
            return null;
        }
        if ($name === 'read') {
            $btn = ReadButton::init($name);
        } elseif ($name === 'edit') {
            $btn = EditButton::init($name);
        } elseif ($name === 'del') {
            $btn = DeleteButton::init($name);
        } else {
            $btn = new PageButton();
        }

        return $btn;
    }

    /**
     * 按钮
     * @param $buttons
     * @return Button[]
     */
    public function buttons($buttons): array
    {
        $data = [];

        if (empty($buttons)) {
            return $data;
        }

        if (is_string($buttons)) {
            $buttons = [$buttons];
        }

        foreach ($buttons as $button) {
            if (is_string($button)) {
                $button = $this->button($button);
            }
            if ($button instanceof Button) {
                $data[] = $button;
            }
        }

        return $data;
    }

    /**
     * @param $buttons
     * @return array
     */
    public function btnTransfer($buttons): array
    {
        $buttons = $this->buttons($buttons);

        $data = [];

        $dictionary = SeeLang::instance()->getLangGroup('btn');

        foreach ($buttons as $btn) {
            $data[] = [
                'text' => $dictionary[$btn->getText()] ?? $btn->getText(),
                'style' => $btn->getStyle(),
                'map' => $btn->getMap() ? Transfer::base64Encode($btn->getMap()) : '',
                'query' => $btn->getQuery() ? http_build_query($btn->getQuery()) : '',
                'event' => $btn->getEvent() ?: uniqid(),
                'url' => $btn->getUrl(),
                'target' => $btn->getTarget(),
                'dialog' => $btn->getDialog() ? Transfer::base64Encode($btn->getDialog()->toArray()) : '',
                'confirm' => $btn->getConfirm() ? Transfer::base64Encode($btn->getConfirm()->toArray()) : ''
            ];
        }

        return $data;
    }

    /**
     * @param $toolbars
     * @return Button[]
     */
    public function toolbars($toolbars): array
    {
        $data = [];

        foreach ($toolbars as $toolbar) {
            if ($toolbar === 'create') {
                $toolbar = CreateToolbar::init($toolbar);
            } elseif ($toolbar === 'del') {
                $toolbar = DeleteToolbar::init($toolbar);
            } elseif (is_string($toolbar)) {
                $toolbar = NormalToolbar::init($toolbar);
            }

            $dialog = $toolbar->getDialog();
            if ($dialog) {
                $toolbar['dialog'] = $toolbar->getDialog()->toArray();
            }

            $confirm = $toolbar->getConfirm();
            if ($confirm) {
                $toolbar['confirm'] = $toolbar->getConfirm()->toArray();
            }

            $toolbar['query'] = http_build_query($toolbar->getQuery());

            $data[] = $toolbar;
        }

        return $data;
    }

    /**
     * @param $controls
     * @return Control[]
     */
    public function controls($controls): array
    {
        $data = [];

        $page = See::config()->page;

        $images = $page->controlImg();
        $password = $page->controlPassword();
        $file = $page->controlFile();
        $hidden = $page->controlHidden();

        foreach ($controls as $control) {

            if (is_string($control)) {
                $required = true;
                if (preg_match('/\.false/', $control)) {
                    $name = str_replace('.false', '', $control);
                    $required = false;
                } else {
                    $name = $control;
                }

                if ($name == 'status') {
                    $control = new RadioControl();
                    $control->setOptions([0 => SeeLang::switch('forbid'), 1 => SeeLang::switch('open')]);
                    $control->setValue(1);
                } elseif ($name == 'sort') {
                    $control = new InputControl();
                    $control->setValue(99);
                } elseif (in_array($name, ['start_time', 'begin_time', 'end_time'])) {
                    $control = new DatetimeControl();
                    $control->setValue(date('Y-m-d H:i:s'));
                } elseif (in_array($name, $images)) {
                    $control = new ImageControl();
                } elseif (in_array($name, $file)) {
                    $control = new FileControl();
                } elseif (in_array($name, $password)) {
                    $control = new PasswordControl();
                } elseif (in_array($name, $hidden)) {
                    $control = new HiddenControl();
                } else {
                    $control = new InputControl();
                }
                $control->setName($name);
                $control->setRequired($required);

            } elseif (is_array($control)) {
                $len = count($control);
                $name = $control[0];
                $second = $control[1] ?? null;
                $third = $control[2] ?? null;

                if ($len == 2 && is_array($second)) {
                    $control = new RadioControl();
                    $control->setName($name);
                    $control->setOptions($second);
                } elseif ($len == 3 && is_array($third)) {
                    if ($second == 'select') {
                        $control = new SelectControl();
                    } else {
                        $control = new RadioControl();
                    }
                    $control->setName($name);
                    $control->setType($second);
                    $control->setOptions($third);
                }
            }

            $name = $control->getName();
            $label = $control->getLabel() ?: $this->transferLabel($name);

            $control->setLabel($label);

            $data[] = $control;
        }

        return $data;
    }
}